/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package rlpw.swing;

import java.util.Comparator;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.event.ListDataListener;

/**
 *
 * @author weinpau
 */
public class JOComboBox<T> extends JComboBox implements View<T> {

    private Model<T> model;
    private SelectModel<T> selected;
    private Filter<T> filter;
    private Comparator<T> sorter;

    public JOComboBox() {
        this(new DefaultModel<T>());
    }

    public JOComboBox(Model<T> m) {

        setDataModel(m);
        setFilter(null);
        model.addView(this);
        selected = new DefaultSelectModel<T>(this);
        selected.setMode(SelectModel.SINGLE);
    }

    @Override
    public void addItem(Object anObject) {
        getDataModel().add((T) anObject);
    }

    @Override
    public T getItemAt(int index) {
        return (T) super.getItemAt(index);
    }

    @Override
    public void insertItemAt(Object anObject, int index) {
        getDataModel().add(new FilteredList<T>(this).toDataModelIndex(index), (T) anObject);
    }

    @Override
    public void removeItem(Object anObject) {
        getDataModel().remove((T) anObject);
    }

    @Override
    public void removeItemAt(int anIndex) {
        removeItem(new FilteredList<T>(this).get(anIndex));
    }

    @Override
    public void removeAllItems() {
        getDataModel().clear();
        updateView();
    }

    @Override
    public T getSelectedItem() {
        return (T) super.getSelectedItem();
    }

    @Override
    public T[] getSelectedObjects() {
        return (T[]) super.getSelectedObjects();
    }

    public void updateView() {


        setModel(new ComboBoxModel() {

            public void setSelectedItem(Object anItem) {
                getSelectModel().setSelected((T) anItem, true);
            }

            public Object getSelectedItem() {
                try {
                    FilteredList<T> fl = new FilteredList<T>(JOComboBox.this);
                    if (getSelectModel().countSelected() > 0) {
                        return getSelectModel().getSelected().get(0);
                    } else if (!fl.isEmpty()) {
                        setSelectedItem(fl.get(0));
                        return getSelectedItem();
                    }
                } catch (Exception excep) {
                }
                return null;
            }

            public int getSize() {
                return new FilteredList<T>(JOComboBox.this).size();
            }

            public Object getElementAt(int index) {
                return new FilteredList<T>(JOComboBox.this).get(index);
            }

            public void addListDataListener(ListDataListener l) {
                getDataModel().addListDataListener(l);
            }

            public void removeListDataListener(ListDataListener l) {
                getDataModel().removeListDataListener(l);
            }
        });

        try {
            FilteredList<T> fl = new FilteredList<T>(this);

            if (!fl.contains(getSelectedItem())) {
                if (!fl.isEmpty()) {
                    setSelectedIndex(0);
                } else {
                    setSelectedItem(null);
                }
            }
        } catch (Exception excep) {
        }

        revalidate();
        repaint();
    }

    public Model<T> getDataModel() {
        return model;
    }

    public void setDataModel(Model<T> model) {
        this.model = model;
        updateView();

    }

    public CheckModel getCheckModel() {
        return null;
    }

    public SelectModel<T> getSelectModel() {
        return selected;
    }

    public Filter<T> getFilter() {
        return filter;
    }

    public void setFilter(Filter<T> filter) {
        if (filter == null) {
            this.filter = new DefaultFilter<T>();
        } else {
            this.filter = filter;
        }

        updateView();
    }

    public void setSorter(Comparator<T> comp) {
        sorter = comp;
        updateView();
    }

    public Comparator<T> getSorter() {
        return sorter;
    }
}
